package com.yyl.common.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 转换实用程序
 */
@Slf4j
public class oConvertUtils {

    // 判断空值
    public static boolean isEmpty(Object object){
        if (object==null){
            return (true);
        }
        if ("".equals(object)){
            return (true);
        }
        return "null".equals(object);
    }
    // 判断非空
    public static boolean isNotEmpty(Object object){
        return object!=null && !object.equals("") && !object.equals("null");
    }
    // 解码 code
    public static String decode(String strIn,String sourceCode,String targetCode){
        return code2code(strIn,sourceCode,targetCode);
    }
    // 字符串编码
    public static String StrToUTF(String strIn,String sourceCode,String targetCode){
        strIn="";
        try{
            strIn=new String(strIn.getBytes(StandardCharsets.ISO_8859_1),"GBK");
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
        return strIn;
    }
    // 2次编码，code
    private static String code2code(String strIn,String sourceCode,String targetCode){
        String strOut=null;
        if (strIn==null || (strIn.trim()).equals("")){
            return strIn;
        }
        try{
            byte[] b=strIn.getBytes(sourceCode);
            for (byte value : b){
                System.out.println(value+" ");
            }
            strOut=new String(b,targetCode);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return strOut;
    }
    // 获取整数类型的
    public static int getInt(String s,int defVal){
        if (s == null || s.equals("")) {
            return (defVal);
        }
        try{
            return (Integer.parseInt(s));
        }catch (NumberFormatException e){
            return (defVal);
        }
    }

    public static int getInt(String s){
        if(s==null || s.equals("")){
            return 0;
        }
        try{
            return (Integer.parseInt(s));
        }catch (NumberFormatException e){
            return 0;
        }
    }
    public static int getInt(String s,Integer df){
        if (s == null || s.equals("")) {
            return df;
        }
        try{
            return (Integer.parseInt(s));
        }catch (NumberFormatException e){
            return 0;
        }
    }

    public static Integer[] getInts(String[] s){
        Integer[] integer=new Integer[s.length];
        for(int i=0;i< s.length;i++){
            integer[i] =Integer.parseInt(s[i]);
        }
        return integer;
    }
    public static double getDouble(String s,double defVal){
        if (s==null || s.equals("")){
            return (defVal);
        }
        try{
            return (Double.parseDouble(s));
        }catch (NumberFormatException e){
            return (defVal);
        }
    }
    public static double getDou(Double s,double defVal){
        if (s==null){
            return (defVal);
        }
        return s;
    }
    public static int getInt(Object object,int defVal){
        if (isEmpty(object)) {
            return (defVal);
        }
        try{
            return (Integer.parseInt(object.toString()));
        }catch (NumberFormatException e){
            return (defVal);
        }
    }

    public static Integer getInt(Object object){
        if (isEmpty(object)){
            return null;
        }
        try{
            return (Integer.parseInt(object.toString()));
        }catch (NumberFormatException e){
            return null;
        }
    }
    public static int getInt(BigDecimal s,int defVal){
        if (s==null){
            return (defVal);
        }
        return s.intValue();
    }
    public static Integer[] getIntegerArray(String[] object){
        int len= object.length;
        Integer[] result=new Integer[len];

        try{
            for(int i=0;i<len;i++){
                result[i] =new Integer(object[i].trim());
            }
            return result;
        }catch (NumberFormatException e){
            return null;
        }

    }
    public static String getString(String s){
        return (getString(s,""));
    }

    /**
     *  转义成 Unicode 编码
     * @param object
     * @return
     */
    public static String getString(Object object){
        if (isEmpty(object)){
            return "";
        }
        return (object.toString().trim());
    }
    public static String getString(int i){
        return (String.valueOf(i));
    }
    public static String getString(float i){
        return (String.valueOf(i));
    }
    public static String getString(String s,String defVal){
        if (isEmpty(s)){
            return (defVal);
        }
        return (s.trim());
    }

    public static long stringToLong(String str){
        long test=0L;
        try{
            test=Long.parseLong(str);
        }catch (Exception ignored){

        }
        return test;
    }
    /**
     * 获取本机IP
     */
    public static String getIp(){
        String ip=null;
        try{
            InetAddress address=InetAddress.getLocalHost();
            ip= address.getHostAddress();
        }catch (UnknownHostException e){
            e.printStackTrace();
        }
        return ip;
    }

    /**
     *  判断一个类 是否为基本数据类型
     * @param clazz 要判断的类
     * @return true 表示为基本类型
     * @throws Exception
     */
    private static boolean isBaseBataType(Class<?> clazz) throws Exception {
        return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Character.class) || clazz.equals(Short.class)||clazz.equals(BigDecimal.class)||clazz.equals(BigInteger.class)||clazz.equals(Boolean.class)||clazz.equals(Date.class)||clazz.isPrimitive());
    }

    /**
     *通过请求获取 IP 地址
     * @param request IP
     * @return IP Address
     */
    public static String getIpAddrByRequest(HttpServletRequest request){
        String ip=request.getHeader("x-forwarded-for");
        if(ip==null || ip.length()==0 || "unknown".equalsIgnoreCase(ip)){
            ip=request.getHeader("Proxy-Client-IP");
        }
        if(ip==null || ip.length()==0 || "unknown".equalsIgnoreCase(ip)){
            ip=request.getHeader("WL-Proxy-Client_IP");
        }
        if (ip == null || ip.length()==0 || "unknown".equalsIgnoreCase(ip)) {
            ip=request.getRemoteAddr();
        }
        return ip;

    }

    /**
     *
     * @return 本机IP
     * @throws SocketException
     */
    public static String getRealIp() throws SocketException{
        String localip=null;// 本机IP，如果没有配置外网IP则返回它
        String netip=null;// 外网IP

        Enumeration<NetworkInterface> netInterfaces=NetworkInterface.getNetworkInterfaces();
        InetAddress ip=null;
        boolean finded=false;// 是否找到外网IP
        while (netInterfaces.hasMoreElements() && !finded){
            NetworkInterface ni=netInterfaces.nextElement();
            Enumeration<InetAddress> address=ni.getInetAddresses();
            while (address.hasMoreElements()){
                ip=address.nextElement();
                if(!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !ip.getHostAddress().contains(":")){// 外网IP
                    netip=ip.getHostAddress();
                    finded=true;
                    break;
                }else if(ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !ip.getHostAddress().contains(":")){// 内网IP
                    localip=ip.getHostAddress();
                }
            }
        }

        if (netip!=null && !"".equals(netip)){
            return netip;
        }else {
            return localip;
        }
    }

    /**
     *  java 去除字符串 中的 空格、回车、换行符、制表符
     * @param str
     * @return
     */
    public static String replaceBlank(String str){
        String dest="";
        if (str != null) {
            Pattern p=Pattern.compile("\\s*|\t|\r|\n");
            Matcher m= p.matcher(str);
            dest= m.replaceAll("");
        }
        return dest;
    }

    /**
     * 判断元素是否在数组内
     * @param substring
     * @param source
     * @return
     */
    public static boolean isIn(String substring,String[] source){
        if (source == null || source.length==0) {
            return false;
        }
        for (int i = 0; i < source.length; i++) {
            String aSource=source[i];
            if(aSource.equals(substring)){
                return true;
            }
        }
        return false;
    }
    /**
     * 获取 Map 对象
     */
    public static Map<Object,Object> getHashMap(){
        return new HashMap<Object, Object>();
    }
    /**
     * SET 转换 MAP
     */
    public static Map<Object, Object> SetToMap(Set<Object> setobj){
        Map<Object, Object> map=getHashMap();
        for(Object o :setobj){
            Map.Entry<Object,Object> entry=(Map.Entry<Object,Object>) o;
            map.put(entry.getKey().toString(),entry.getValue()==null ? "" : entry.getValue().toString().trim());
        }
        return map;
    }

    /**
     *  内部ip
     * @param ipAddress
     * @return
     */
    public static boolean isInnerIP(String ipAddress){
        boolean isInnerIp=false;
        long ipNum=getIpNum(ipAddress);
        long aBegin=getIpNum("10.0.0.0");
        long aEnd=getIpNum("10.255.255.255");
        long bBegin=getIpNum("172.16.0.0");
        long bEnd=getIpNum("172.31.255.255");
        long cBegin=getIpNum("192.168.0.0");
        long cEnd=getIpNum("192.168.255.255");
        isInnerIp=isInner(ipNum,aBegin,aEnd) || isInner(ipNum,bBegin,bEnd) || isInner(ipNum,cBegin,cEnd) || ipAddress.equals("127.0.0.1");
        return isInnerIp;
    }
    // 获取 ip 号码
    private static long getIpNum(String ipAddress){
        String[] ip=ipAddress.split("\\.");
        long a=Integer.parseInt(ip[0]);
        long b=Integer.parseInt(ip[1]);
        long c=Integer.parseInt(ip[2]);
        long d=Integer.parseInt(ip[3]);
        return a*256*256*256+b*256*526+c*256+d;
    }
    private static boolean isInner(long userIp,long begin,long end){
        return (userIp>=begin) && (userIp<=end);
    }
    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。
     * 如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。</br>
     * 例如：hello_world->helloWorld
     *
     * @param name 转换前的下划线大写方式命名的字符串
     * @return 转换后的驼峰式命名的字符串
     */
    public static String camelName(String name){
        StringBuilder result=new StringBuilder();
        // 快速 检查
        if (name == null || name.isEmpty()){
            // 没必要转换
            return "";
        }else if (!name.contains("_")) {
           // 不含下划线，仅将字母小写
           return name.substring(0,1).toLowerCase()+name.substring(1).toLowerCase();
        }
      // 用下滑线 将原始字符串分割
        String[] camels=name.split("_");
        for(String camel :camels){
            // 跳过 原始字符串中开头、结尾的下划线或双重下划线
            if(camel.isEmpty()){
                continue;
            }
            // 处理真正的驼峰片段
            if(result.length()==0){
                // 第一个 驼峰片段，全部字母都小写
                result.append(camel.toLowerCase());
            }else {
                // 其他的驼峰片段，首字母大写
                result.append(camel.substring(0,1).toLowerCase());
                result.append(camel.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }
    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。
     * 如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。</br>
     * 例如：hello_world,test_id->helloWorld,testId
     *
     * @return 转换后的驼峰式命名的字符串
     */
    public static String camelNames(String names){
        if(names==null || names.equals("")){
            return null;
        }
        StringBuilder sf=new StringBuilder();
        String[] fs=names.split(",");
        for(String field : fs){
          field =camelName(field);
            sf.append(field).append(",");
        }
        String result=sf.toString();
        return result.substring(0,result.length()-1);
    }
    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。(首字母写)
     * 如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。</br>
     * 例如：hello_world->HelloWorld
     *
     * @param name 转换前的下划线大写方式命名的字符串
     * @return 转换后的驼峰式命名的字符串
     */
    public static String camelNameCapFirst(String name){
        StringBuilder result=new StringBuilder();
        // 快速检查
        if(name==null || name.isEmpty()){
            // 没必要转换
            return "";
        }else if (!name.contains("_")){
            // 不含下划线，仅将首字母小写
            return name.substring(0,1).toUpperCase()+name.substring(1).toLowerCase();
        }
        //用下划线将原始字符串分割
        String[] camels=name.split("_");
        for (String camel:camels){
            // 跳过原始字符串开头，结尾的下划线或双重下滑线
            if(camel.isEmpty()){
                continue;
            }
            // 其他的驼峰片段，首字母大写
            result.append(camel.substring(0,1).toLowerCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }
    /**
     * 将驼峰命名转化成下划线
     *
     * @param para
     * @return
     */
    public static String camelToUnderline(String para){
        if(para.length()<3){
            return para.toLowerCase();
        }
        StringBuilder sb=new StringBuilder(para);
        int temp=0;// 定位
        // 从第三个字符开始 避免命名不规范
        for(int i=2;i<para.length();i++){
            if(Character.isUpperCase(para.charAt(i))){
                sb.insert(i+temp,"_");
                temp+=1;
            }
        }
        return sb.toString().toLowerCase();
    }
    
    /**
     * 随机数
     *
     * @param place 定义随机数的位数
     */
    public static String randomGen(int place){
        String base = "qwertyuioplkjhgfdsazxcvbnmQAZWSXEDCRFVTGBYHNUJMIKLOP0123456789";
        StringBuilder sb=new StringBuilder();
        Random rd=new Random();
        for (int i=0;i<place;i++){
            sb.append(base.charAt(rd.nextInt(base.length())));
        }
        return sb.toString();
    }
    /**
     * 获取类的所有属性，包括父类
     *
     * @param object
     * @return
     */
    public static Field[] getAllFields(Object object){
        Class<?> clazz=object.getClass();
        List<Field> fieldList=new ArrayList<>();
        while (clazz!=null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz=clazz.getSuperclass();
        }
        Field[] fields=new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }
    /**
     * 将map的key全部转成小写
     *
     * @param list
     * @return
     */
    public static List<Map<String,Object>> toLowerCasePageList(List<Map<String,Object>> list){
        List<Map<String, Object>> select=new ArrayList<>();
        for(Map<String,Object> row : list){
            Map<String,Object> resultMap=new HashMap<>();
            Set<String> keySet=row.keySet();
            for(String key :keySet){
                String newKey=key.toLowerCase();
                resultMap.put(newKey,row.get(key));
            }
            select.add(resultMap);
        }
        return select;
    }
    /**
     * 将entityList转换成modelList
     *
     * @param fromList
     * @param tClass
     * @param <F>
     * @param <T>
     * @return
     */
    public static <F,T> List<T> entityListToModelList(List<F> fromList,Class<T> tClass){
        if (fromList.isEmpty()){
            return null;
        }
        List<T> tList=new ArrayList<>();
        for(F f :fromList){
            T t=entityToModel(f,tClass);
            tList.add(t);
        }
        return tList;
    }
    public static <F,T> T entityToModel(F entity,Class<T> modelClass){
        log.debug("entityToModel : Entity属性的值赋值到Model");
        Object model=null;
        if (entity == null || modelClass ==null) {
            return null;
        }
        try{
           model=modelClass.newInstance();
        }catch (InstantiationException e){
            log.error("entityToModel : 实例化异常",e);
        }catch (IllegalAccessException e){
            log.error("entityToModel : 安全权限异常",e);
        }
        BeanUtils.copyProperties(entity,model);
        return (T) model;
    }
    /**
     * 判断 list 是否为空
     *
     * @param list
     * @return true or false
     * list == null		: true
     * list.size() == 0	: true
     */
    public static boolean listIsEmpty(Collection<?> list){
        return (list==null || list.size()==0);
    }
    /**
     * 判断 list 是否不为空
     *
     * @param list
     * @return true or false
     * list == null		: false
     * list.size() == 0	: false
     */
    public static boolean listIsNotEmpty(Collection<?> list){
        return !listIsEmpty(list);
    }
}
